package com.lj.infoisland.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lj.infoisland.common.convention.result.Result;
import com.lj.infoisland.common.convention.result.Results;
import com.lj.infoisland.domain.common.CommonOption;
import com.lj.infoisland.domain.dto.NewsDTO;
import com.lj.infoisland.domain.dto.PutFileDTO;
import com.lj.infoisland.domain.po.News;
import com.lj.infoisland.domain.po.NewsCategories;
import com.lj.infoisland.domain.vo.HotNewsVO;
import com.lj.infoisland.domain.vo.NewsVO;
import com.lj.infoisland.domain.vo.UserInfoVO;
import com.lj.infoisland.service.MinioService;
import com.lj.infoisland.service.NewsCategoriesService;
import com.lj.infoisland.service.NewsService;
import com.lj.infoisland.service.UsersService;
import com.lj.infoisland.util.UniqueRandomStringGenerator;
import com.lj.infoisland.util.UserContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static com.lj.infoisland.util.JwtUtil.extractUserIdFromToken;

/*
 * @description 新闻控制层
 * @author 龙洁
 * @create 2024-10-25 下午1:49
 */
@RestController
@RequestMapping("/news")
public class NewsController {

    @Value("${minio.FILE_PREFIX}")
    private String FILE_PREFIX;
    @Resource
    private UsersService usersService;
    @Resource
    private NewsService newsService;
    @Resource
    private MinioService minioService;
    @Resource
    private NewsCategoriesService newsCategoriesService;

    /**
     * 从URL中提取文件名
     *
     * @param url 文章URL
     * @return 文件名
     */
    private static String extractFileName(String url) {
        // 找到最后一个'/'的位置
        int lastSlashIndex = url.lastIndexOf('/');
        // 找到第一个'?'的位置，表示查询参数的开始
        int queryStartIndex = url.indexOf('?');

        // 如果'?'不存在，那么文件名就是最后一个'/'之后的所有字符
        if (queryStartIndex == -1) {
            return url.substring(lastSlashIndex + 1);
        } else {
            // 截取最后一个'/'和第一个'?'之间的字符串作为文件名
            return url.substring(lastSlashIndex + 1, queryStartIndex);
        }
    }

    public static String extractFilename(String url) {
        // 从 URL 中提取文件名部分
        int lastSlashIndex = url.lastIndexOf('/');
        int questionMarkIndex = url.indexOf('?', lastSlashIndex);
        if (questionMarkIndex != -1) {
            return url.substring(lastSlashIndex + 1, questionMarkIndex);
        } else {
            return url.substring(lastSlashIndex + 1);
        }
    }

    /**
     * 获取文章分类列表
     *
     * @return 文章分类列表
     */
    @GetMapping("/getNewsCategoriesList")
    public Result<List<CommonOption>> getNewsCategoriesList() {
        return newsCategoriesService.getNewsCategoriesList();
    }

    /**
     * 获取文章分类列表admin
     *
     * @return 文章分类列表
     */
    @GetMapping("/getNewsCategoriesAdminList")
    public Result<List<NewsCategories>> getNewsCategoriesAdminList() {
        return newsCategoriesService.getNewsCategoriesAdminList();
    }

    /**
     * 删除文章分类列表admin
     *
     * @return 文章分类列表
     */
    @GetMapping("/deleteNewsCategories")
    public Result<?> deleteNewsCategories(Integer id) {
        newsCategoriesService.deleteNewsCategories(id);
        return Results.success();
    }

    /**
     * 新增文章分类列表admin
     *
     * @return 文章分类列表
     */
    @GetMapping("/addNewsCategories")
    public Result<?> addNewsCategories(@RequestParam("name") String name) {
        newsCategoriesService.addNewsCategories(name);
        return Results.success();
    }

    /**
     * 获取热门文章列表
     *
     * @return 热门文章列表
     */
    @GetMapping("/getHotNewsList")
    public Result<List<HotNewsVO>> getHotNewsList() {
        return newsService.getHotNewsList();
    }

    /**
     * 获取文章列表
     *
     * @param pageNum    分页num
     * @param pageSize   分页size
     * @param categoryId 分类id
     * @return 文章列表·
     */
    @GetMapping("/getNewsList")
    public Result<IPage<NewsVO>> getNewsList(HttpServletRequest request, @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                             @RequestParam(value = "pageSize", defaultValue = "12") Integer pageSize,
                                             @RequestParam(value = "categoryId", defaultValue = "0") String categoryId) {
        Page<News> newsPage = new Page<>(pageNum, pageSize);
        IPage<NewsVO> list = newsService.getNewsList(request, newsPage, categoryId);
        return Results.success(list);
    }

    /**
     * 获取收藏
     *
     * @return 收藏文章分类列表
     */
    @GetMapping("/getCollectNewsList")
    public Result<List<NewsVO>> getCollectNewsList() {
        return newsService.getCollectNewsList();
    }

    /**
     * 获取头条文章
     *
     * @return 头条文章
     */
    @GetMapping("/getHotNew")
    public Result<NewsVO> getHotNew(@RequestParam("categoryId") Integer categoryId) {
        return newsService.getHotNew(categoryId);
    }

    /**
     * 获取用户文章列表
     *
     * @param pageNum  分类num
     * @param pageSize 分页size
     * @return 用户文章列表
     */
    @GetMapping("/getUserNewsList")
    public Result<IPage<NewsVO>> getUserNewsList(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                                 @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        Page<News> newsPage = new Page<>(pageNum, pageSize);
        IPage<NewsVO> list = newsService.getUserNewsList(newsPage);
        return Results.success(list);
    }

    /**
     * 获取用户文章数量
     *
     * @return 用户文章数量
     */
    @GetMapping("/getUserNewsCount")
    public Result<Long> getUserNewsCount() {
        long count = newsService.count(Wrappers.lambdaQuery(News.class).eq(News::getUserUniqueId, UserContext.getUser().getUserUniqueId()));
        return Results.success(count);
    }

    /**
     * 获取文章详情
     *
     * @param id 文章id
     * @return 文章详情
     * @throws IOException 读取文件异常
     */
    @GetMapping("/getNewsDetailById")
    public Result<NewsVO> getNewsDetailById(@RequestParam("id") String id, HttpServletRequest request) throws IOException {
        // 从请求头中获取token
        String token = request.getHeader("Token");
        if (token != null) {
            // 提取token中的userId
            String userUniqueId = extractUserIdFromToken(token);
            if (userUniqueId != null) {
                // 查询数据库获取用户信息
                UserInfoVO user = usersService.getUserInfo(userUniqueId).getData();
                // 将用户信息存储到ThreadLocal中
                UserContext.setUser(user);
            }
        }
        News news = newsService.getById(id);
        ByteArrayOutputStream downloadFile = minioService.getDownloadFile(extractFileName(news.getContentUrl()));
        NewsVO bean = BeanUtil.toBean(news, NewsVO.class);
        bean.setCoverImage(FILE_PREFIX + news.getCoverImage());
        bean.setCategoryName(newsCategoriesService.getById(news.getCategoryId()).getName());
        bean.setUsername(usersService.getUserNameById(news.getUserUniqueId()));
        bean.setContentText(downloadFile.toString(StandardCharsets.UTF_8));
        // 增加浏览量
        newsService.addViewNum(id);
        return Results.success(bean);
    }

    /**
     * 发布文章
     *
     * @param newsDTO 文章信息
     * @return 文章id
     * @throws IOException
     */
    @PostMapping("/publishNews")
    public Result<String> publishNews(@RequestBody NewsDTO newsDTO) throws IOException {
        String fileName = UniqueRandomStringGenerator.generateUniqueString() + ".md";
        PutFileDTO putFileDTO = new PutFileDTO();
        putFileDTO.setFileName(fileName);
        putFileDTO.setContentText(newsDTO.getContentText());
        String contentUrl = putContent(putFileDTO);
        newsService.publishNews(newsDTO, contentUrl);
        return Results.success(fileName);
    }

    @PostMapping("/putContent")
    public String putContent(@RequestBody PutFileDTO putFileDTO) throws IOException {
        // 将字符串转换为字节数组
        byte[] bytes = putFileDTO.getContentText().getBytes(StandardCharsets.UTF_8);
        // 使用字节数组创建ByteArrayInputStream
        InputStream inputStream = new ByteArrayInputStream(bytes);
        minioService.put(inputStream, "text/markdown", putFileDTO.getFileName());

        return minioService.getDownloadUrl(putFileDTO.getFileName());
    }

    /**
     * 修改文章
     *
     * @param newsDTO 文章信息
     * @return void
     * @throws IOException
     */
    @PostMapping("/reviseNews")
    public Result<Void> reviseNews(@RequestBody NewsDTO newsDTO) throws IOException {
        String filename = UniqueRandomStringGenerator.generateUniqueString() + ".md";
        // 将字符串转换为字节数组
        byte[] bytes = newsDTO.getContentText().getBytes(StandardCharsets.UTF_8);
        // 使用字节数组创建ByteArrayInputStream
        InputStream inputStream = new ByteArrayInputStream(bytes);
        minioService.put(inputStream, "text/markdown", filename);
        String contentUrl = minioService.getDownloadUrl(filename);
        String coverImage = newsDTO.getCoverImage();
        //
        coverImage = extractFilename(coverImage);
        newsService.update(Wrappers.lambdaUpdate(News.class)
                .eq(News::getId, newsDTO.getId())
                .set(News::getContentUrl, contentUrl)
                .set(News::getDescription, newsDTO.getDescription())
                .set(News::getCategoryId, newsDTO.getCategoryId())
                .set(News::getCoverImage, coverImage)
                .set(News::getTitle, newsDTO.getTitle()));
        return Results.success();
    }

    /**
     * 获取相似文章
     *
     * @param newsId
     * @return
     */
    @GetMapping("/getSimilarNews")
    public Result<List<NewsVO>> getSimilarNews(@RequestParam("newsId") String newsId) {
        return newsService.getSimilarNews(newsId);
    }

    @GetMapping("/updateNewsStatus")
    public Result<?> updateNewsStatus(@RequestParam("id") String id, @RequestParam("published") Boolean published) {
        newsService.updateNewsStatus(id, published);
        return Results.success();
    }


    /**
     * 修改文章发布状态
     *
     * @param id 文章id
     * @return void
     */
    @PutMapping("/alterNewsPublished")
    public Result<Void> alterNewsPublished(@RequestParam("id") String id) {
        News byId = newsService.getById(id);
        newsService.update(Wrappers.lambdaUpdate(News.class).eq(News::getId, id).set(News::getIsPublished, byId.getIsPublished() == 1 ? 0 : 1));
        return Results.success();
    }

    /**
     * 点赞文章
     *
     * @param newId 文章id
     */
    @GetMapping("/likeNews")
    public Result<?> likeNews(@RequestParam("newId") String newId) {
        return newsService.likeNews(newId);
    }

    /**
     * 收藏文章
     *
     * @param newId 文章id
     */
    @GetMapping("/collectNews")
    public Result<?> collectNews(@RequestParam("newId") String newId) {
        return newsService.collectNews(newId);
    }

    /**
     * 是否点赞
     *
     * @param newId 文章id
     * @return false没有点赞，true点赞
     */
    @GetMapping("/isLikeNews")
    public Result<Boolean> isLikeNews(@RequestParam("newId") String newId, HttpServletRequest request) {
        // 从请求头中获取token
        String token = request.getHeader("Token");
        if (token != null) {
            // 提取token中的userId
            String userUniqueId = extractUserIdFromToken(token);
            if (userUniqueId != null) {
                // 查询数据库获取用户信息
                UserInfoVO user = usersService.getUserInfo(userUniqueId).getData();
                // 将用户信息存储到ThreadLocal中
                UserContext.setUser(user);
            }
        }
        return Results.success(newsService.isLiked(newId));
    }

    /**
     * 是否收藏
     *
     * @param newId 文章id
     * @return false没有收藏，true收藏
     */
    @GetMapping("/isCollectNews")
    public Result<Boolean> isCollectNews(@RequestParam("newId") String newId, HttpServletRequest request) {
        // 从请求头中获取token
        String token = request.getHeader("Token");
        if (token != null) {
            // 提取token中的userId
            String userUniqueId = extractUserIdFromToken(token);
            if (userUniqueId != null) {
                // 查询数据库获取用户信息
                UserInfoVO user = usersService.getUserInfo(userUniqueId).getData();
                // 将用户信息存储到ThreadLocal中
                UserContext.setUser(user);
            }
        }
        return Results.success(newsService.isCollect(newId));
    }

    /**
     * 搜索文章
     *
     * @return
     */
    @GetMapping("/searchNews")
    public Result<IPage<NewsVO>> searchNews(@RequestParam("keyword") String keyword,
                                            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                            @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
        return Results.success(newsService.searchNews(keyword, pageNum, pageSize));
    }

    /**
     * 删除文章
     *
     * @return void
     */
    public Result<Void> deleteNews() {
        return Results.success();
    }
}
